package com.binance.feign.ribbon.config;

import com.binance.feign.ribbon.cache.CachingSpringLoadBalancerFactory;
import com.binance.feign.ribbon.client.LoadBalancerFeignClient;
import com.netflix.loadbalancer.ILoadBalancer;
import feign.Feign;
import feign.Request;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.loadbalancer.LoadBalancedBackOffPolicyFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalancedRetryListenerFactory;
import org.springframework.cloud.netflix.feign.FeignAutoConfiguration;
import org.springframework.cloud.netflix.feign.support.FeignHttpClientProperties;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;

/**
 * Created by Fei.Huang on 2018/9/7.
 * <p>
 * 注意事项：
 * <p>
 * 1.引用该Starter，需要在SpringBootApplication中 exclude 原生 FeignRibbonClientAutoConfiguration.class，即:
 *
 * @EnableAutoConfiguration(exclude={org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration.class}) <p>
 * 2.引用该Starter，需要在SpringBootApplication中 import 当前 FeignRibbonClientAutoConfiguration.class，即:
 * @Import(FeignRibbonClientAutoConfiguration.class)
 */
@ConditionalOnClass({ILoadBalancer.class, Feign.class})
@Configuration
@AutoConfigureBefore(FeignAutoConfiguration.class)
@EnableConfigurationProperties({FeignHttpClientProperties.class})
@Import({HttpClientFeignLoadBalancedConfiguration.class,
        OkHttpFeignLoadBalancedConfiguration.class,
        DefaultFeignLoadBalancedConfiguration.class})
public class FeignRibbonClientAutoConfiguration {

    @Bean
    @Primary
    @ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
    public CachingSpringLoadBalancerFactory retryabeCachingLBClientFactory(
            SpringClientFactory factory,
            LoadBalancedBackOffPolicyFactory loadBalancedBackOffPolicyFactory,
            LoadBalancedRetryListenerFactory loadBalancedRetryListenerFactory) {
        return new CachingSpringLoadBalancerFactory(factory, loadBalancedBackOffPolicyFactory, loadBalancedRetryListenerFactory);
    }

    @Bean
    @ConditionalOnMissingBean
    public Request.Options feignRequestOptions() {
        return LoadBalancerFeignClient.DEFAULT_OPTIONS;
    }
}